package metrics

import (
	"gitee.com/captials-team/ubdframe/src/domain/configstc"
	v1log "gitee.com/captials-team/ubdframe/src/pkg/logs"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"net/http"
)

type PrometheusIndicator struct {
	l        v1log.ILog
	ch       chan IndicData
	registry *prometheus.Registry

	conf configstc.MonitorReportConfig
}

// NewPrometheusIndicator 指标上报器-prometheus pull模式
func NewPrometheusIndicator(conf configstc.MonitorReportConfig, l v1log.ILog) *PrometheusIndicator {
	st := &PrometheusIndicator{
		l:        l,
		ch:       make(chan IndicData, 64),
		conf:     conf,
		registry: prometheus.NewRegistry(),
	}
	go st.runHttp()
	go st.bgReport()
	return st
}

func (ind *PrometheusIndicator) Registry() *prometheus.Registry {
	return ind.registry
}

func (ind *PrometheusIndicator) bgReport() {
	m := map[string]*prometheus.GaugeVec{}
	for {
		select {
		case data := <-ind.ch:
			ind.l.Info("[Indicator]%s: %f %s", data.Name, data.Value, data.Unit)
			var gauge *prometheus.GaugeVec
			var exist bool

			metricName := ind.conf.Namespace + "." + data.Name
			if gauge, exist = m[metricName]; !exist {
				var labels []string
				for k, _ := range data.EntireLabels() {
					labels = append(labels, k)
				}
				m[metricName] = prometheus.NewGaugeVec(prometheus.GaugeOpts{
					Namespace: ind.conf.Namespace,
					Name:      data.Name,
					Help:      "prometheus by pull",
				}, labels)
				gauge = m[metricName]

				err := ind.registry.Register(gauge)
				if err != nil {
					ind.l.Error("prometheus register fail %s", err)
				}
			}
			gauge.With(data.EntireLabels()).Set(data.Value)

		}
	}
}

func (ind *PrometheusIndicator) runHttp() {
	http.Handle("/metrics", promhttp.HandlerFor(
		ind.registry,
		promhttp.HandlerOpts{},
	))
	err := http.ListenAndServe(ind.conf.Host, nil)
	if err != nil {
		ind.l.Error("http stop %s", err)
	}
}

// Report 上报数据
func (ind *PrometheusIndicator) Report(data IndicData) {
	ind.ch <- data
}
